package online.listener;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

/**
 * @Auther: 狼芒
 * @Date: 2021/11/17 23:41
 * @Descrintion:
 * @version: 1.0
 */
@Slf4j
@Component
public class RabbitMQCallback implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnsCallback {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 注入到rabbitTemplate中
     *
     * PostConstruct：在其他注解都加载完后再进行加载
     */
    @PostConstruct
    public void init() {
        rabbitTemplate.setConfirmCallback(this::confirm);
        rabbitTemplate.setReturnsCallback(this::returnedMessage);
    }

    /**
     * 交换机确认回调方法
     * 1、发送消息，交换机接收到了 回调
     *      1.1
     * @param correlationData 保存消息回调的ID及相关信息
     * @param ack 交换机收到消息标识  收到：true，未收到 false
     * @param cause 产生问题的原因，成功就没有原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData == null ? "" : correlationData.getId();
        String msg = correlationData == null ? "" : new String(correlationData.getReturned().getMessage().getBody());
        if (ack) {
            log.info("交换机已经收到id为:{} 的消息为：{}", id, msg);
        } else {
            log.info("交换机还未收到id为:{} 的消息为：{}，原因为: {}", id, msg, cause);
        }
    }

    /**
     * 发送消息到交换机后，路由错误的话，消息回退给生产者
     * @param returnedMessage
     */
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        Message message = returnedMessage.getMessage();
        String msg = new String(message.getBody());
        String exchange = returnedMessage.getExchange();
        int replyCode = returnedMessage.getReplyCode();
        String replyText = returnedMessage.getReplyText();
        String routingKey = returnedMessage.getRoutingKey();
        log.error("消息：{},被交换机：{}回退，路由：{}，原因：{}， 状态：{}", msg, exchange,routingKey, replyText, replyCode);
    }
}
